/* 
 * File:   Fact.cpp
 * Author: Gab'z
 * 
 * Created on 4 juin 2012, 09:40
 */

#include "Fact.h"
#include "../../../Context.h"
#include "../../literal/Stack.h"
#include "model/command/literal/Integer.h"

namespace calculator {

    Fact::Fact(const std::string name) : UnaryOperator(name) {
    }

    Fact::Fact(const Fact& orig) : UnaryOperator(orig._name) {
    }

    Fact::~Fact() {
    }

    std::string Fact::isExecutable() const {
        if (Context::getInstance()->getCurrentStack()->size() == 0) return "Empty stack";
        const Integer* integer = dynamic_cast<const Integer*> (Context::getInstance()->getCurrentStack()->getConstant(0));
        if (integer == 0 || (int) integer->value() < 0) return "Must be a positive Integer";
        return "";
    }

    Fact* Fact::clone() const {
        return new Fact(_name);
    }

    const Number* Fact::apply(const Number* number) const throw (ArithmeticException) {
        const Integer* integer = dynamic_cast<const Integer*> (number);
        if (integer == 0 || (int) integer->value() < 0) throw ArithmeticException("Stack top must be positive  or null Integer");
        int res = 1;
        for (unsigned int i = 1; i <= (unsigned int) integer->value(); i++) {
            res *= i;
        }
        return new Integer(res);
    }
}